Azure Functions(Node.js)からAzure Database for PostgresSQLへアクセスしてみる
いわさです。
最近たまに Azure FunctionsやAzure Database for PostgreSQL を触っているのですが関数からデータベースへアクセスさせてみることにしました。
- Visual Studio CodeのAzure App Service拡張のリモートエラーの通知機能が良かった話 | DevelopersIO
- Azure Database for PostgreSQLにてサーバーパラメータのタイムゾーンが反映されない問題を調べた | DevelopersIO
node-postgresqlを使う
まず、Azure Functionsにはバインドという概念があり、リソース間での接続を行うことが出来ます。
しかし、本日時点では、Azure Database for PostgreSQLは入出力バインディングにもトリガーにも対応していません。(Azure SQL Databaseについてはバインドについてはプレビューでサポートされているようです)
Azureに限らず、サーバーレス関数はRDBMSとの相性の問題もあり、Cosmos DBのような NoSQLデータベースが使われることのほうが多い印象はあります。
そこで、今回はNode.jsからPostgreSQLへアクセスするために、node-postgresql
を使っています。
やってみた
Azure Database for PostgreSQL
今回はAzure Database for PostgreSQLはフレキシブルサーバーで作成し、事前にサンプルDBとテーブル・レコードを作成しておきます。
postgres=> create database hogedb; CREATE DATABASE postgres=> \c hogedb psql (14.1, server 13.5) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) You are now connected to database "hogedb" as user "postgres". hogedb=> create table hogetbl (id integer, name varchar(10)); CREATE TABLE hogedb=> insert into hogetbl (id, name) values (1, 'aaa'); INSERT 0 1 hogedb=> insert into hogetbl (id, name) values (2, 'bbb'); INSERT 0 1 hogedb=> insert into hogetbl (id, name) values (3, 'ccc'); INSERT 0 1 hogedb=> select * from hogetbl; id | name ----+------ 1 | aaa 2 | bbb 3 | ccc (3 rows)
後ほど接続設定で使うので、Azureポータルから接続文字列を取得します。
node-postgresql
ではいくつかの接続オプションがあるのですが、今回はURIを使いたいと思います。
また、関数からデータベースへのアクセスもシンプルにVNETなどは使わずにパブリックアクセスさせます。
そのため、データベース側のファイアウォール設定でAzureサービスからのアクセスを許可させておきます。
Azure Functions
エディターはVisual Studio Codeを使います。
事前にAzure Functions拡張機能をインストールし、サブスクリプションもセットアップした状態を想定しています。
まずは以下の手順に従って関数を作成します。
トリガーは要件にあわせて選択すれば良いと思いますが、今回はcURLで動作確認しようと思うのでHTTPトリガーを使いました。
一旦ローカルで実行させて問題ないかだけ確認しておきましょう。
$ curl http://localhost:7071/api/HttpTrigger1 This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.
良さそうですね。
次にnode-postgresql
をインストールし、PostgreSQLにアクセスするようにコードを変更していきます。
$ npm install pg npm WARN 0402postgres@1.0.0 No description npm WARN 0402postgres@1.0.0 No repository field. npm WARN 0402postgres@1.0.0 No license field. + pg@8.7.3 added 15 packages from 9 contributors and audited 15 packages in 3.584s found 0 vulnerabilities
node-postgres
では接続情報はデフォルトで環境変数から読み込まれます。プログラム側で指定することも出来ます。
この記事では便宜上指定してみます。パスワードまで含まれたコードなんて危険な感じがかなりしますが、実際に利用する際は最後に案内するベストプラクティスに従ってください。
module.exports = async function (context, req) { const { Client } = require('pg'); const connectionString = 'postgres://fuga:piyo@hoge.postgres.database.azure.com/hogedb?sslmode=require' const client = new Client({ connectionString, }) await client.connect(); const result = await client.query('select * from hogetbl'); client.end(); context.res = { body: result.rows }; }
上記をローカルで確認してみましょう。
$ curl http://localhost:7071/api/HttpTrigger1 [ { "id": 1, "name": "aaa" }, { "id": 2, "name": "bbb" }, { "id": 3, "name": "ccc" } ]
事前にサンプルで用意しておいたレコードが取得出来ていますね。
デプロイして動作確認
Visual Studio Codeを使ってAzureへデプロイします。
手順は先程の関数セットアップの記事に記載されています。
Visual Studio Code周りの拡張機能ほんと充実してますよね。
デプロイの出力ログから発行URLも確認出来るので、そのまま確認用のリクエストを送信してみます。
7:37:41 hoge-functions: Starting deployment... 7:37:41 hoge-functions: Creating zip package... 7:37:41 hoge-functions: Uploading zip package to storage container... 7:37:41 hoge-functions: Zip package size: 110 kB 7:37:43 hoge-functions: Deployment successful. 7:37:43 hoge-functions: Started postDeployTask "npm install (functions)". 7:37:54 hoge-functions: Syncing triggers... 7:37:56 hoge-functions: Querying triggers... 7:37:57 hoge-functions: HTTP Trigger Urls: HttpTrigger1: https://hoge-functions.azurewebsites.net/api/httptrigger1 $ curl https://hoge-functions.azurewebsites.net/api/httptrigger1 [ { "id": 1, "name": "aaa" }, { "id": 2, "name": "bbb" }, { "id": 3, "name": "ccc" } ]
うまく接続出来ているようです。
さいごに
この記事ではまずは第一歩ということで、アクセスするところまでを試してみました。
実際に導入を考えると、この状態ではセキュリティや様々な面で課題があるという点をご認識ください。
例えば、以下はAzure SQL Databaseの場合の話をされていますが、MaxConnectionの課題などは、今回の構成だとどのFaaSでも問題になりやすい点でそのための対処を通常行います。
Azure Functionsのベストプラクティスには上記も含めて推奨事項が掲載されているのでよく確認したいところです。